/***********************************************************************
 * Module:  RecordPage.java
 * Author:  wy
 * Purpose: Defines the Class RecordPage
 ***********************************************************************/

package wxdb.record;

import java.util.*;
import static java.sql.Types.*;

import wxdb.query.Constant;
import wxdb.query.IntConstant;
import wxdb.query.StringConstant;
import wxdb.tx.Transaction;
import wxdb.ui.Global;

/*
 * a bunch of records 
 * this class is used to iterate records within a page
 */

public class RecordPage {
	public static final int EMPTY=0, INUSE=1;
	
   private int pid;
   private TableInfo ti;
   private int slotsize;
   private int currentslot;
   
   /** @param pid 
    * @param ti
    */
   public RecordPage(int pid, TableInfo ti) {
	   this.pid = pid;
	   this.ti = ti;
	   currentslot = -1;
	   slotsize = ti.getRecordLen() + Transaction.getIntSize();
   }
   
   public boolean next() {
      return searchFor(INUSE);
   }
   
   
   
   public Constant getField(String fldName){
	   int type = ti.getSchema().getType(fldName);
	   if(type == INTEGER)
		   return new IntConstant(getInt(fldName));
	   else if(type == VARCHAR)
		   return new StringConstant(getString(fldName));
	   return null;
   }
   
   /** @param slotnum
    */
   public void moveTo(int slotnum) {
      currentslot = slotnum;
   }
   
   /** @param fldName
    */
   public int getInt(String fldName) {
      int intOffset = getFieldPos(fldName);
      return Transaction.getInt(ti.getDbid(), pid, intOffset);
      
   }
   
   /**  @param fldName
    */
   public String getString(String fldName) {
      int strOffset = getFieldPos(fldName);
      return Transaction.getString(ti.getDbid(), pid, strOffset);
   }
   
   public void setVal(String fldname, Constant val) {
	   if (ti.getSchema().getType(fldname) == INTEGER)
		   setInt(fldname, (Integer)val.asJavaVal());
	   else
		   setString(fldname, (String)val.asJavaVal());
   }
   
   /** @param fldName 
    * @param ival
    */
   public void setInt(String fldName, int ival) {
      int intOffset = getFieldPos(fldName);
      Transaction.setInt(ti.getDbid(), pid, intOffset, ival);
   }
   
   /** @param fldNam 
    */
   public void setString(String fldName, String sval) {
      int strOffset = getFieldPos(fldName);
      Transaction.setString(ti.getDbid(), pid, strOffset, sval, ti.getRecordLen());
   }
   
   public boolean insert() {
      currentslot = -1;
      if(searchFor(EMPTY)){
    	  Transaction.setInt(ti.getDbid(), pid, getCurrentPos(), INUSE);
    	  return true;
      }
      return false;
   }
   
   public void delete() {
      Transaction.setInt(ti.getDbid(), pid, getCurrentPos(), EMPTY);
   }
   
   public int getCurrentlot() {
      return currentslot;
   }
   
   public boolean isValidSlot() {
      return getCurrentPos()+slotsize <= Global.STORAGE_PAGE_SIZE;
   }
   
   //position is at the beginning of the current slot
   public int getCurrentPos() {
      return currentslot*slotsize;
   }
   
   /**
    * @param flag
    */
   public boolean searchFor(int flag) {
      ++currentslot;
      int getFlag;
      while(isValidSlot()){
    	  if((getFlag=Transaction.getInt(ti.getDbid(), pid, getCurrentPos())) == flag){
    		  return true;
    	  }
    	  ++currentslot;
      }
      return false;
   }
   
   /** @param fldNam
    */
   public int getFieldPos(String fldName) {
      int pos = getCurrentPos() + Transaction.getIntSize() + ti.getOffset(fldName);
      return pos;
   }

}